home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / LIBRARY / STRAOB / MISCCORE.INC < prev    next >
Text File  |  1995-02-24  |  46KB  |  1,845 lines

  1.  
  2. {section  AddBackSlash }
  3. Function  AddBackSlash(s1 : string) : string;
  4. var s : string;
  5.      begin
  6.      if (length(s1) > 0) and (s1[length(s1)] <> '\') then
  7.           s := s1 + '\'
  8.      else s := s1;
  9.      AddBackSlash := s;
  10.      end;
  11.  
  12.  
  13. {section  BooleanStr }
  14. Function  BooleanStr( B : boolean ) : string;
  15.     begin
  16.     if B then
  17.          BooleanStr := 'YES'
  18.     else BooleanStr := 'NO ';
  19.     end;
  20.  
  21.  
  22. {section  BreakLine }
  23. Function  BreakLine(var s : string; bklen : integer) : string;
  24. var s1 : string;
  25.     ll  : integer;
  26.     alldone : boolean;
  27.      begin
  28.      RemoveTrailing(s,' ');
  29.      s1 := s;
  30.      if length(s) > bklen then
  31.           begin
  32.           ll := bklen;
  33.           alldone := false;
  34.           while (ll > 0) and not alldone do
  35.                begin
  36.                if      s[ll] = ' ' then alldone := true
  37.                else if s[ll] = ',' then alldone := true
  38.                else dec(ll);
  39.                end;
  40.           if ll > 1 then
  41.                begin
  42.                s1 := copy(s,1,ll);
  43.                delete(s,1,ll);
  44.                end
  45.           else begin
  46.                s1 := copy(s,1,bklen);
  47.                delete(s,1,bklen);
  48.                end;
  49.           end
  50.      else s := '';
  51.      Breakline := s1;
  52.      end;
  53.  
  54.  
  55. {section  BreakLineChr }
  56. Function  BreakLineChr(var s : string; bklen : integer; ch : char) : string;
  57. var s1 : string;
  58.     ll  : integer;
  59.     done : boolean;
  60.      begin
  61.      RemoveTrailing(s,' ');
  62.      s1 := s;
  63.      if length(s) > bklen then
  64.           begin
  65.           ll := bklen;
  66.           done := false;
  67.           while (ll > 0) and not done do
  68.                begin
  69.                if      s[ll] = ch then done := true
  70.                else dec(ll);
  71.                end;
  72.           if ll > 1 then
  73.                begin
  74.                s1 := copy(s,1,ll);
  75.                delete(s,1,ll);
  76.                end
  77.           else begin
  78.                s1 := copy(s,1,bklen);
  79.                delete(s,1,bklen);
  80.                end;
  81.           end
  82.      else s := '';
  83.      BreakLineChr := s1;
  84.      end;
  85.  
  86.  
  87. {SECTION Buf16ToHexStr }
  88. Function Buf16ToHexStr(addr : longint; count : integer; var xbuf; flag : boolean) : string;
  89.             {[STRING] One line of the DUMP output}
  90. var s,asc : string;
  91.     i,j   : integer;
  92.     buf   : array[1..16] of byte;
  93.      begin
  94.      s := ''; asc := '';
  95.      move(xbuf,buf,16);
  96.      j := 16;
  97.      if count < 16 then j := count;
  98.      if count < 1  then j := 1;
  99.      for i := 1 to j do
  100.           begin
  101.           s := s + ByteToHex(buf[i]) + ' ';
  102.           if buf[i] > 31 then asc := asc + chr(buf[i])
  103.           else asc := asc + '.';
  104.           end;
  105.      Buf16ToHexStr := FmtAddress(addr,6,flag)+': '+ leftstr(s,48) +
  106.                                  ' | ' + asc;
  107.      end;
  108.  
  109.  
  110. {section  ByteToHex }
  111. Function  ByteToHex( B : byte) : string;
  112. var s : string[2];
  113.     b1 : byte;
  114.      begin
  115.      s := '00';
  116.      b1 := (b and $F0) div 16;
  117.      if b1 < 10 then s[1] := chr(b1+48)
  118.      else s[1] := chr(b1+55);
  119.      b1 := b and $0F;
  120.      if b1 < 10 then s[2] := chr(b1+48)
  121.      else s[2] := chr(b1+55);
  122.      ByteToHex := s;
  123.      end;
  124.  
  125.  
  126. {section  CheckSectionID }
  127. Function  CheckSectionID(s,secttag : string) : string;
  128.                         {[STRING] checks line s, returning section name if this is a section line }
  129. var s1,s2 : string;
  130.      begin
  131.      s1 := '';
  132.      if CompareUpL(s,secttag,length(secttag)) then
  133.           begin
  134.           s2 := s;
  135.           delete(s2,1,length(secttag));
  136.           trim(s2);
  137.           s1 := GetLeftStr(s2,' ');
  138.           end;
  139.      CheckSectionID := s1;
  140.      end;
  141.  
  142.  
  143. {section CenterStr }
  144. Function CenterStr(s : string; w : byte) : string;
  145. { Centers a string in a field of specified width }
  146. var NewStr : string;
  147.     i       : word;
  148.     p       : word;
  149.      begin
  150.      FillChar(NewStr, SizeOf(NewStr), ' ');
  151.      NewStr[0] := CHR(w);
  152.      p         := (w - length(s)) SHR 1;
  153.      for i := 1 to length(s) do NewStr[p + i] := s[i];
  154.      CenterStr := NewStr
  155.      end;
  156.  
  157.  
  158. {section ChangeDir }
  159. Function ChangeDir(dirname : string) : boolean;
  160.                  {[FILE] does CD <dir> command (if a filename is provided, goes to dir)}
  161. var fn    : string;
  162.     j,err : integer;
  163.      begin
  164.      j := pos('.',dirname);
  165.      if j > 0 then
  166.           fn := DeleteBackSlash(FilePathStr(dirname))
  167.      else fn := DeleteBackSlash(dirname);
  168.      writeln('ChangeDir [',fn,']');
  169.      {$I-} ChDir(fn); {$I+}
  170.      err := IOResult;
  171.      if err <> 0 then writeln('ChangeDir failed ',err);
  172.      ChangeDir := (err = 0);
  173.      end;
  174.  
  175.  
  176.  
  177.  
  178. {SECTION  CheckYesNo }
  179. Function  CheckYesNo(pr : string; default : char) : boolean;
  180. var s : string[1];
  181.      begin
  182.      write(pr);
  183.      if UpCase(default) = 'Y' then
  184.           write(' (Y/n) ')
  185.      else write(' (y/N) ');
  186.      readln(s);
  187.      if s = '' then s := default;
  188.      s := UpCaseStr(s);
  189.      writeln('[',s,']');
  190.      if s = 'N' then
  191.           CheckYesNo := false
  192.      else CheckYesNo := true;
  193.      end;
  194.  
  195.  
  196.  
  197. {section CompareBUFS }
  198. Function CompareBUFS(var rec1,rec2; size : integer) : boolean;
  199.                   {[MISC] Lifted almost exactly from TPC Language Guide }
  200. type TBytes = array[0..65534] of byte;
  201. var  N      : word;
  202.      begin
  203.      N := 0;
  204.      while (N < size) and ( TBytes(rec2)[N] = TBytes(rec1)[N]) do inc(N);
  205.      CompareBUFS := ( N = size );
  206.      end;
  207.  
  208.  
  209.  
  210. {SECTION  Compare }
  211. Function  Compare(s1,s2 :string) : boolean;
  212.                         {[STRING] Compares s1 to s2 - s2 can have wildcards }
  213. var i    : integer;
  214.     done : boolean;
  215.     ch   : char;
  216.      begin
  217.     { writeln('Compare  [',s1,'] [',s2,']');}
  218.      Compare := true; i := 0; done := false;
  219.      while (i < length(s2)) and not done do
  220.           begin
  221.           inc(i);
  222.           ch := s2[i];
  223.           case ch of
  224.                '?'   : begin end;   {match fine}
  225.                '*'   : begin Compare := true; done := true; end;
  226.                else    begin
  227.                        if s1[i] <> ch then
  228.                             begin
  229.                            { writeln('char ',i,' ',s1[i],' ',ch); }
  230.                             Compare := false;
  231.                             done := true;
  232.                             end;
  233.                        end;
  234.                end;
  235.           end;
  236.      if not done and (i <> length(s1)) then
  237.           begin
  238.          { writeln('ending ',i,' ',length(s1)); }
  239.           Compare := false;
  240.           end;
  241.      end;
  242.  
  243.  
  244. {SECTION  CompareTrim }
  245. Function  CompareTrim(s1,s2 :string) : boolean;
  246.                         {[STRING] Compares s1 to s2, trims first }
  247.      begin
  248.      CompareTrim := Compare(trimstr(s1),trimstr(s2));
  249.      end;
  250.  
  251.  
  252. {SECTION  CompareL }
  253. Function  CompareL(s1,s2 :string; len : integer) : boolean;
  254.                         {[STRING] Compares s1 to s2 for length len }
  255.      begin
  256.      CompareL := Compare(leftstr(s1,len),leftstr(s2,len));
  257.      end;
  258.  
  259.  
  260. {SECTION  CompareUpL }
  261. Function  CompareUpL(s1,s2 :string; len : integer) : boolean;
  262.                         {[STRING] Compares s1 to s2 for length len (s1,s2 shifted UP)}
  263.      begin
  264.      CompareUpL := Compare(UpCaseStr(leftstr(s1,len)),
  265.                            UpCaseStr(leftstr(s2,len)));
  266.      end;
  267.  
  268.  
  269. {section  CompareStrs }
  270. Function  CompareStrs(s1,s2 : string; compmode,casemode : integer) : boolean;
  271.           {[STRING] - comprehensive string comparisons, NO WildCards }
  272. var ok : boolean;
  273.     st1, st2 : string;
  274.      begin
  275.      ok := true;
  276.      st1 := s1; if casemode = UpCaseMode then st1 := UpCaseStr(s1);
  277.      st2 := s2; if casemode = UpCaseMode then st2 := UpCaseStr(s2);
  278.      case compmode of
  279.          EQmode : if (st1  <>  st2) then ok := false;
  280.          GEmode : if (st1  <   st2) then ok := false;
  281.          LEmode : if (st1  >   st2) then ok := false;
  282.          GTmode : if (st1  <   st2) then ok := false;
  283.          LTmode : if (st1  >   st2) then ok := false;
  284.          end;
  285.      CompareStrs := ok;
  286.      end;
  287.  
  288.  
  289. {section  CompareStrsEQ }
  290. Function  CompareStrsEQ(s1,s2 : string; casemode : integer) : boolean;
  291.           {[STRING] - string comparisons, NO WildCards, EQ only }
  292. var st1, st2 : string[80];
  293.      begin
  294.      if casemode = UpCaseMode then
  295.           st1 := UpCaseStr(s1)
  296.      else st1 := s1;
  297.      if casemode = UpCaseMode then
  298.           st2 := UpCaseStr(s2)
  299.      else st2 := s2;
  300.      CompareStrsEQ := (st1 = st2);
  301.      end;
  302.  
  303.  
  304. {section CompressStr }
  305. Function CompressStr(s1 : string) : string;
  306. var ls,j,rc : integer;
  307.     s,s2    : string;
  308.     ch      : char;
  309.     begin
  310.      S := S1;
  311.     ls := length(s);
  312.     if ls < 3 then
  313.         begin
  314.         CompressStr := s;
  315.         exit;
  316.         end;
  317.     s2 := '';
  318.     j := 1;
  319.     while j <= ls  do
  320.         begin
  321.         if (j > (ls-2)) or (s[j] <> s[j+1]) or (s[j] <> s[j+2]) then
  322.             s2 := s2 + s[j]
  323.         else
  324.             begin
  325.             ch := s[j];
  326.             inc(j);
  327.             rc := 0;
  328.             s2 := s2 + s[j];
  329.             while (j <= ls) and (s[j] = ch) do
  330.                 begin
  331.                 inc(rc);
  332.                 inc(j);
  333.                 end;
  334.             s2 := s2 + chr(160+rc);
  335.             if j <= ls then s2 := s2 + s[j];
  336.             end;
  337.         inc(j);
  338.         end;
  339.     CompressStr := s2;
  340.     end;
  341.  
  342.  
  343. {section  ConstStr }
  344. Function  ConstStr(C : Char; N : Integer) : string;
  345. var S : string;
  346.     begin
  347.     if N < 0 then N := 0;
  348.     S[0] := Chr(N);
  349.     FillChar(S[1],N,C);
  350.     ConstStr := s;
  351.     end;
  352.  
  353.  
  354.  
  355. {section  CopyRemove }
  356. Function  CopyRemove(var s : string; f,l : integer) : string;
  357.                             {[STRING] copies then deletes a substring }
  358. var len : integer;
  359.      begin
  360.      CopyRemove := '';
  361.      if (f > 0) and (f <= l) and (l <= length(s)) then
  362.           begin
  363.           len := (l - f) + 1;
  364.           CopyRemove := copy(s,f,len);
  365.           delete(s,f,len);
  366.           end;
  367.      end;
  368.  
  369.  
  370. {section  CurrDTimeString }
  371. Function  CurrDTimeString : string;
  372.     var
  373.         temp1,temp2       : string;
  374.         Yr, Mo, Da, dow   : word;
  375.         Hr, Mn, Sc, sc100 : word;
  376.         i                 : integer;
  377.         l                 : longint;
  378.     begin
  379.     GetDate(yr,mo,da,dow);
  380.     l := (yr-1900)*tenthousand + mo*onehundred +da;
  381.     str(l:6,temp1);
  382.     GetTime(hr,mn,sc,sc100);
  383.     l := hr*tenthousand + mn*onehundred +sc;
  384.     str(l:6,temp2);
  385.     for i := 1 to 6 do
  386.         begin
  387.         if temp1[i] = ' ' then temp1[i] := '0';
  388.         if temp2[i] = ' ' then temp2[i] := '0';
  389.         end;
  390.     CurrDTimeString := temp1+temp2;
  391.     end;
  392.  
  393.  
  394. {section  DefaultDriveStr }
  395. Function  DefaultDriveStr : string;
  396. var s : string;
  397.     begin
  398.     GetDir(0,s);
  399.     DefaultDriveStr := s;
  400.     end;
  401.  
  402.  
  403. {section  DeleteBackSlash }
  404. Function  DeleteBackSlash(s1 : string) : string;
  405. var s : string;
  406.      begin
  407.      if (length(s1) > 0) and (s1[length(s1)] = '\') then
  408.           s := copy(s1,1,length(s1)-1)
  409.      else s := s1;
  410.      DeleteBackSlash := s;
  411.      end;
  412.  
  413.  
  414. {section DirExists }
  415. Function DirExists(dirname : string) : boolean;
  416.                  {[FILE] sees if directory exists (a full file name may be provided)}
  417. var fn : string;
  418.     j  : integer;
  419.      begin
  420.      j := pos('.',dirname);
  421.      if j > 0 then fn := AddBackSlash(FilePathStr(dirname)) + '.'
  422.      else fn := AddBackslash(dirname)+'.';
  423.      DirExists := fileexists(fn);
  424.      end;
  425.  
  426.  
  427. {section DirExistsMSG }
  428. Function DirExistsMSG(dirname,yesmsg,nomsg : string) : boolean;
  429.                  {[FILE] sees if directory exists (a full file name may be provided)}
  430. var ok : boolean;
  431.      begin
  432.      ok := DirExists(dirname);
  433.      if ok and (yesmsg <> '') then
  434.           writeln('Directory exists [',dirname,'].  ',yesmsg)
  435.      else if not ok and (nomsg <> '') then
  436.           writeln('Directory does not exist [',dirname,'].  ',nomsg);
  437.      DirExistsMSG := ok;
  438.      end;
  439.  
  440.  
  441. {section  DirTag }
  442. Function  DirTag(path : string) : string;
  443. var s : string;
  444.     i : integer;
  445.      begin
  446.      s := path;
  447.      i := pos('\',s);
  448.      while i > 0 do
  449.           begin
  450.           delete(s,1,i);
  451.           i := pos('\',s);
  452.           end;
  453.      Dirtag := s;
  454.      end;
  455.  
  456.  
  457. {section DnCaseStr }
  458. Function DnCaseStr(s : string) : string;
  459. { Converts a string to lower case characters }
  460. var i : integer;
  461.     b : byte;
  462.      begin
  463.      for i := 1 to length(s) do
  464.           begin
  465.           b := ord(s[i]);
  466.           if (b > 64) and (b < 91) then s[i] := chr(b+32);
  467.           end;
  468.      DnCaseStr := s;
  469.      end;
  470.  
  471.  
  472. {section DollarStr }
  473. Function DollarStr( R : real; L : integer ) : string;
  474. var S : string;
  475.     begin
  476.     S := '';
  477.     case L of
  478.         4..15  : Str(R:L:2,S);
  479.         else     S := ConstStr('*',L);
  480.         end;
  481.     DollarStr := s;
  482. end;
  483.  
  484.  
  485.  
  486. {section  DOSErrStr }
  487. Function  DOSErrStr(err : integer) : string;
  488.      begin
  489.      DOSErrStr := 'DOS Error ('+integerstr(err,4)+')';
  490.      end;
  491.  
  492.  
  493. {section  DOSErrStrBig }
  494. Function  DOSErrStrBig(err : integer) : string;
  495. { DOS file error returns - eliminated 10/2/94 - too big}
  496. var s : string;
  497.      begin
  498.      case err of
  499.          0        : s :=  'ok ' ;
  500.          1        : s :=  'Invalid function number' ;
  501.          2        : s :=  'file not found' ;
  502.          3        : s :=  'Path not found' ;
  503.          4        : s :=  'Too many open files' ;
  504.          5        : s :=  'File access denied' ;
  505.          6        : s :=  'Invalid file handle' ;
  506.          12       : s :=  'Invalid file access code' ;
  507.          15       : s :=  'Invalid drive number' ;
  508.          18       : s :=  'No More files' ;
  509.          100      : s :=  'Disk read error' ;
  510.          101      : s :=  'Disk write error' ;
  511.          102      : s :=  'File not assigned' ;
  512.          103      : s :=  'File not open' ;
  513.          104      : s :=  'File not opened for input' ;
  514.          105      : s :=  'File not opened for output' ;
  515.          150      : s :=  'Disk is write protected' ;
  516.          152      : s :=  'drive not ready' ;
  517.          159      : s :=  'Printer out of paper' ;
  518.          160      : s :=  'Device write fault' ;
  519.          162      : s :=  'Hardware failure' ;
  520.          200      : s :=  'Division by zero' ;
  521.          201      : s :=  'Range check' ;
  522.          202      : s :=  'Stack overflow' ;
  523.          203      : s :=  'Heap overflow' ;
  524.          204      : s :=  'Invalid pointer operation' ;
  525.          205..207 : s := 'Floating point problem' ;
  526.          208..209 : s := 'Overlay problem' ;
  527.          210..214 : s := 'Object problem' ;
  528.          else       s := 'USER ERR ';
  529.          end;
  530.      DOSErrStrBig := 'DOS Error('+integerstr(err,4)+') '+s+'. ';
  531.      end;
  532.  
  533.  
  534. {section  DumpRecBufInHexO }
  535. Procedure DumpRecBufInHexO(recnum : longint; recsiz : integer; var rec; OUTP : OUTProc_type);
  536.               {[DEBUG] Dumps a record buffer in HEX, user supplied I/O }
  537.  
  538. var l,rs : longint;
  539.     rbuf : array[1..2048] of byte;
  540.     zbuf : array[1..16] of byte;
  541.     i,j  : integer;
  542.      begin
  543.      i := 1; rs := recsiz;
  544.      if rs > sizeof(rbuf) then rs := sizeof(rbuf);
  545.      fillchar(rbuf,sizeof(rbuf),0);
  546.      move(rec,rbuf,rs);
  547.      l := (recnum-1)*recsiz;
  548.      OUTP('Record - '+longintstr(recnum,7)+'    size='+integerstr(rs,4)+
  549.              '    fileaddr:'+longintstr(l,7));
  550.      while i < recsiz do
  551.           begin
  552.           move(rbuf[i],zbuf,16);
  553.           OUTP(Buf16ToHexStr(i,(recsiz-i)+1,zbuf,false));
  554.           i := i + 16;
  555.           end;
  556.      if recsiz > 16 then OUTP(' ');
  557.      end;
  558.  
  559.  
  560. {section  DumpRecBufInHex }
  561. Procedure DumpRecBufInHex(recnum : longint; recsiz : integer; var rec);
  562.             {[DEBUG] Dumps a record buffer in HEX }
  563.      begin
  564.      DumpRecBufInHexO(recnum,recsiz,rec,OUTProc);
  565.      end;
  566.  
  567.  
  568. {section  EquivalentFile }
  569. Function  EquivalentFile(fn1,fn2 : string) : boolean;
  570. var same : boolean;
  571.     sr1, sr2 : searchrec;
  572.      begin
  573.      same := false;
  574.      if (fileInfo(fn1,'',sr1) = 0) and
  575.         (fileInfo(fn2,'',sr2) = 0) then
  576.           begin
  577.           if (sr1.size = sr2.size) and
  578.              (sr1.time = sr2.time) then same := true;
  579.           end;
  580.      EquivalentFile := same;
  581.      end;
  582.  
  583.  
  584. {section  EraseFile }
  585. Procedure EraseFile(s : string);
  586. var f : file;
  587.     ch : char;
  588.     begin
  589.     assign (f,s);
  590.     {$I-}
  591.     reset (f);
  592.     {$I+}
  593.     if IOResult = 0 then
  594.         begin
  595.         close(f);
  596.         Erase(f);
  597.         end;
  598.     end;
  599.  
  600.  
  601. {section  ExtractDelimitedStr }
  602. Function  ExtractDelimitedStr(var s : string; lchar,rchar : char) : string;
  603.                        {[STRING] extracts inside of a delimited substring }
  604. var i,j  : integer;
  605.     s1   : string;
  606.      begin
  607.      ExtractDelimitedStr :=  '';
  608.      i := pos(lchar,s);
  609.      if i > 0 then
  610.           begin
  611.           j := pos(rchar,s);
  612.           if (j > i) then
  613.                begin
  614.                s1 :=  CopyRemove(s,i,j);
  615.                delete(s1,1,1);
  616.                if length(s1) > 0 then delete(s1,length(s1),1);
  617.                ExtractDelimitedStr :=  s1;
  618.                end;
  619.           end;
  620.      end;
  621.  
  622.  
  623. {section ExtractPath }
  624. Function ExtractPath(var fname : string) : string;
  625. var i : integer;
  626.     npath : string;
  627.     begin
  628.     npath := '';
  629.     i := pos('\',fname);
  630.     while i > 0 do
  631.          begin
  632.          npath := npath + copy(fname,1,i);
  633.          delete(fname,1,i);
  634.          i := pos('\',fname);
  635.          end;
  636.     ExtractPath := npath;
  637.     end;
  638.  
  639.  
  640. {section FileDate }
  641. Function FileDate(fname : string; ext : string) : longint;
  642. var l : longint;
  643.     fn : string;
  644.     SR : searchrec;
  645.      begin
  646.      fn := fname;
  647.      l := 0;
  648.      if ext <> '' then ForceExt(fn,ext);
  649.      FindFirst(fn,anyfile,SR);
  650.      if dosError = 0 then l := SR.time;
  651.      FileDate := l;
  652.      end;
  653.  
  654.  
  655. {section FileBytes }
  656. Function FileBytes(fname : string; ext : string) : longint;
  657. var l : longint;
  658.     fn : string;
  659.     SR : searchrec;
  660.      begin
  661.      fn := fname;
  662.      l := 0;
  663.      if ext <> '' then ForceExt(fn,ext);
  664.      FindFirst(fn,anyfile,SR);
  665.      if dosError = 0 then l := SR.size;
  666.      FileBytes := l;
  667.      end;
  668.  
  669.  
  670. {section FileExists }
  671. Function FileExists(FName : String) : boolean;
  672. var f     : file;
  673.     fAttr : word;
  674.      begin
  675.      assign(f, FName);
  676.      GetFAttr(f, fAttr);
  677.      FileExists := (DosError = 0)
  678.           { and ((fAttr and Directory) = 0)} {took out 7/14/94 }
  679.            and ((fAttr and VolumeID)  = 0)
  680.      end;  { FileExists }
  681.  
  682.  
  683. {section FileExistsMsg }
  684. Function FileExistsMsg(fname : string; yesmsg,nomsg : string) : boolean;
  685.            {[FILE] Checks file existance and writes appropriate MSG if not "" }
  686.      begin
  687.      FileExistsMsg := true;
  688.      if fileexists(fname) then
  689.           begin
  690.           if yesmsg <> '' then
  691.                writeln('File exists [',fname,']  ',yesmsg);
  692.           FileExistsMsg := true;
  693.           end
  694.      else begin
  695.           if nomsg <> '' then
  696.                writeln('File does not exist [',fname,']  ',nomsg);
  697.           FileExistsMsg := false;
  698.           end;
  699.      end;
  700.  
  701.  
  702. {section FileInfo }
  703. Function FileInfo(filespec : string; ext : string;
  704.                    var SR : searchrec) : integer;
  705. var fn : string;
  706.     err : integer;
  707.      begin
  708.      err := 0;
  709.      fn := filespec;
  710.      if ext <> '' then ForceExt(fn,ext);
  711.      FindFirst(fn,anyfile,SR);
  712.      FileInfo := dosError;
  713.      end;
  714.  
  715.  
  716. {section  FileExtStr }
  717. Function  FileExtStr(fname : string) : string;
  718. var dir,nam,ext : string;
  719.      begin
  720.      FSplit(fname,dir,nam,ext);
  721.      if ext[1] = '.' then delete(ext,1,1);
  722.      FileExtStr := ext;
  723.      end;
  724.  
  725.  
  726. {section  FileNameStr }
  727. Function  FileNameStr(fname : string) : string;
  728. var dir,nam,ext : string;
  729.      begin
  730.      FSplit(fname,dir,nam,ext);
  731.      FileNameStr := nam + ext;
  732.      end;
  733.  
  734.  
  735. {section  FilePathStr }
  736. Function  FilePathStr(fname : string) : string;
  737. var dir,nam,ext : string;
  738.      begin
  739.      FSplit(fname,dir,nam,ext);
  740.      FilePathStr := dir;
  741.      end;
  742.  
  743.  
  744. {section  FileRootStr }
  745. Function  FileRootStr(fname : string) : string;
  746. var dir,nam,ext : string;
  747.      begin
  748.      FSplit(fname,dir,nam,ext);
  749.      FileRootStr := nam;
  750.      end;
  751.  
  752.  
  753. {section FindAndReplaceStr }
  754. Function FindAndReplaceStr(str,fstr,rstr : string; both,all : boolean) : string;
  755.                  {[STRING] finds fstr replaces with rstr, options}
  756. var s,s1,f1s : string;
  757.     i,j    : integer;
  758.     ok : boolean;
  759.      begin
  760.      s   := str;
  761.      if both then
  762.           begin
  763.           f1s := UpCaseStr(fstr);
  764.           s1  := UpCaseStr(s);
  765.           end
  766.      else begin
  767.           f1s := fstr;
  768.           s1  := s;
  769.           end;
  770.      ok := true;
  771.      j := 0;
  772.      while ok do
  773.           begin
  774.           i := pos(f1s,s1);
  775.           if (i > 0) and (j < i) then    {recursion problem}
  776.                begin
  777.                j := i;
  778.                delete(s,i,length(f1s));
  779.                insert(rstr,s,i);
  780.                delete(s1,i,length(f1s));
  781.                insert(rstr,s1,i);
  782.                end
  783.           else ok := false;
  784.           if not all then ok := false;
  785.           if i > 200 then ok := false;  { by 'a' -> 'aa' }
  786.           end;
  787.      FindAndReplaceStr := s;
  788.      end;
  789.  
  790.  
  791. {SECTION FmtAddress }
  792. Function FmtAddress( a : longint; l : integer; flag : boolean) : string;
  793.           {[STRING] formats a longint optionally as hex - for DUMP }
  794. var s : string;
  795.     x : byte;
  796.      begin
  797.      if not Flag then
  798.           s := LongIntStr(a,l)
  799.      else begin
  800.           s := '  ';
  801.           x := byte(a div 256);
  802.           s := s + ByteToHex(x);
  803.           x := byte(a AND $FF);
  804.           s := s + ByteToHex(x);
  805.           end;
  806.      FmtAddress := s;
  807.      end;
  808.  
  809.  
  810.  
  811. {section FmtChr }
  812. Function FmtChr(b : byte) : string;
  813. var s : string[5];
  814.     begin
  815.     s := '<--->';
  816.     case b of
  817.         0..31, 127  : s := '<' + FmtCvtChr(b) + '>';
  818.         32..126     : s :=  chr(b);
  819.         160..254    : begin
  820.                       str(b:3,s);
  821.                       s := '<' + s + '>';
  822.                       end;
  823.        end;
  824.     FmtChr := s;
  825.     end;
  826.  
  827.  
  828. {section FmtCvtChr }
  829. Function FmtCvtChr(b : byte) : string;
  830. var s : string[3];
  831.     begin
  832.     s := '---';
  833.     case b of
  834.         0  : s := 'NUL';
  835.         1  : s := 'SOH';
  836.         2  : s := 'STX';
  837.         3  : s := 'ETX';
  838.         4  : s := 'EOT';
  839.         5  : s := 'ENQ';
  840.         6  : s := 'ACK';
  841.         7  : s := 'BEL';
  842.         8  : s := 'BS ';
  843.         9  : s := 'HT ';
  844.        10  : s := 'LF ';
  845.        11  : s := 'VT ';
  846.        12  : s := 'FF ';
  847.        13  : s := 'CR ';
  848.        14  : s := 'SO ';
  849.        15  : s := 'SI ';
  850.        16  : s := 'DLE';
  851.        17  : s := 'DC1';
  852.        18  : s := 'DC2';
  853.        19  : s := 'DC3';
  854.        20  : s := 'DC4';
  855.        21  : s := 'NAK';
  856.        22  : s := 'SYN';
  857.        23  : s := 'ETB';
  858.        24  : s := 'CAN';
  859.        25  : s := 'EM ';
  860.        26  : s := 'SUB';
  861.        27  : s := 'ESC';
  862.        28  : s := 'FS ';
  863.        29  : s := 'GS ';
  864.        30  : s := 'RS ';
  865.        31  : s := 'US ';
  866.        127 : s := 'DEL';
  867.        else  begin
  868.              if b > 31 then s := chr(b) + '  ';
  869.              end;
  870.        end;
  871.     FmtCvtChr := s;
  872.     end;
  873.  
  874.  
  875. {section  FmtHMS }
  876. Function  FmtHMS(hr, mn, sc : word) : string;
  877. var s : string[8];
  878.     l : longint;
  879.      begin
  880.      s := '        ';
  881.      l := (hr+onehundred)*tenthousand + mn*onehundred +sc;
  882.      str(l:8,s);
  883.   {   if s[3] = '0' then s[3] := ' '; }
  884.      FmtHMS :=  s[3] + s[4] + ':' + s[5] + s[6] + ':' +  s[7] + s[8];
  885.      end;
  886.  
  887.  
  888. {section  FmtKstr }
  889. Function  FmtKstr(l : longint) : string;
  890. var s : string[10];
  891.      begin
  892.      s := '**';
  893.      str((l div $400),s);
  894.      FmtKstr := s + 'k';
  895.      end;
  896.  
  897.  
  898. {section  FmtKstrComma }
  899. Function  FmtKstrComma(l : longint) : string;
  900. var s : string;
  901.      begin
  902.      s := '**';
  903.      str((l div $400),s);
  904.      if length(s) > 3 then insert(',',s,length(s)-2);
  905.      FmtKstrComma := s + 'k';
  906.      end;
  907.  
  908.  
  909. {section FmtStr }
  910. Function FmtStr(s : string) : string;
  911. var s1 : string;
  912.     i : integer;
  913.      begin
  914.      s1 := '';
  915.      if length(s) > 0 then for i := 1 to length(s) do
  916.           begin
  917.           s1 := s1 + FmtChr(ord(s[i]));
  918.           end;
  919.      fmtStr := s1;
  920.      end;
  921.  
  922.  
  923. {section  FmtYMD }
  924. Function  FmtYMD(Yr, Mo, Da : word) : string;
  925. var s : string;
  926.     l : longint;
  927.      begin
  928.      l := yr*tenthousand + mo*onehundred +da;
  929.      str(l:8,s);
  930.      if s[5] = '0' then s[5] := ' ';
  931.      FmtYMD :=  s[5] + s[6] + '/' + s[7] + s[8] + '/' +  s[3] + s[4];
  932.      end;
  933.  
  934.  
  935. {section  ForceExt }
  936. Procedure ForceExt(var fname : string; ext : string);
  937. var i : integer;
  938.     begin
  939.     i := pos('.',fname);
  940.     if i > 0 then fname := copy(fname,1,i-1);
  941.     if ext[1] = '.' then fname := fname + ext
  942.     else fname := fname + '.' + ext;
  943.     end;
  944.  
  945.  
  946. {section  ForcePath }
  947. Procedure ForcePath(var fname : string; pathname : string);
  948. var i : integer;
  949.     xpath,path : string;
  950.     begin
  951.     path  := pathname;
  952.     xpath := ExtractPath(fname); { take out path and throw away}
  953.     if path = '' then
  954.          begin
  955.          getdir(0,xpath);
  956.          path := addbackslash(defaultdrivestr)+xpath;
  957.          end;
  958.     i := pos('.',pathname);
  959.     if i > 0 then path  := ExtractPath(pathname); { keep the path part }
  960.     fname := addbackslash(path) + fname;
  961.     end;
  962.  
  963.  
  964.  
  965. {section ForceRenameFile }
  966. Function ForceRenameFile(fname1,fname2 : string) : boolean;
  967.                   {[FILE] Erases file 2 first. }
  968.      begin
  969.      ForceRenameFile := false;
  970.      EraseFile(fname2);
  971.      if RenameFile(fname1,fname2) then ForceRenameFile := true;
  972.      end;
  973.  
  974.  
  975. {section ForceRenameToBak }
  976. Function ForceRenameToBAK(fname : string) : boolean;
  977. var fn1 : string;
  978.      begin
  979.      ForceRenameToBAK := true;
  980.      fn1 := fname;
  981.      ForceExt(fn1,'BAK');
  982.      if not ForceRenameFile(fname,fn1) then
  983.           begin
  984.           ForceRenameToBAK := false;
  985.           writeln('unable to rename [',fname,']  to [',fn1,']');
  986.           end;
  987.      end;
  988.  
  989.  
  990. {section  FormatDTime }
  991. Function  FormatDTime : string;
  992. var Yr, Mo, Da, dow   : word;
  993.     Hr, Mn, Sc, sc100 : word;
  994.     begin
  995.     GetDate(yr,mo,da,dow);
  996.     GetTime(hr,mn,sc,sc100);
  997.     FormatDTime :=  FmtYMD(yr,mo,da) + ' ' + FmtHMS(hr,mn,sc);
  998.     end;
  999.  
  1000.  
  1001. {section  FormatDTime00 }
  1002. Function  FormatDTime00 : string;
  1003. var Yr, Mo, Da, dow   : word;
  1004.     Hr, Mn, Sc, sc100 : word;
  1005.     begin
  1006.     GetDate(yr,mo,da,dow);
  1007.     GetTime(hr,mn,sc,sc100);
  1008.     FormatDTime00 :=  FmtYMD(yr,mo,da) + ' ' + FmtHMS(hr,mn,sc)+
  1009.                       '.' + integerstr(sc100+100,2);
  1010.     end;
  1011.  
  1012.  
  1013. {section GetNumber }
  1014. Function GetNumber( var astring : string) : real;
  1015. var x       : real;
  1016.     bstring : string;
  1017.     error   : integer;
  1018.     begin
  1019.     x := 0;
  1020.     bstring := GetString(astring);
  1021.     if length(bstring) > 0 then
  1022.         begin
  1023.         val(bstring,x,error);
  1024.         if (error <> 0) then
  1025.             writeln(' val conversion error  * ',bstring,' *  ',error);
  1026.         end;
  1027.     GetNumber := x;
  1028.     end;
  1029.  
  1030.  
  1031.  
  1032. {section  GetSTring }
  1033. Function  GetString ( var s : string) : string;
  1034. var s1 : string;
  1035.     i,l     : integer;
  1036.      begin
  1037.      i := pos(',',s);
  1038.      if i > 0 then
  1039.           begin
  1040.           GetString := copy(s,1,i-1);
  1041.           delete(s,1,i);
  1042.           end
  1043.      else begin
  1044.           GetString := s;
  1045.           s := '';
  1046.           end;
  1047.      end;
  1048.  
  1049.  
  1050.  
  1051. {section  HexAddressToLongInt }
  1052. Function  HexAddressToLongInt(s : string) : longint;
  1053. var l1,l2,l : longint;
  1054.     s1,s2 : string[5];
  1055.     i    : integer;
  1056.      begin
  1057.      i := pos(':',s);
  1058.      if i > 0 then
  1059.           begin
  1060.           s1 := copy(s,1,i-1);
  1061.           s2 := copy(s,i+1,length(s)-i);
  1062.           end
  1063.      else begin
  1064.           s1 := '';
  1065.           s2 := s;
  1066.           end;
  1067.      l1 := hextolongint(s1);
  1068.      l2 := hextolongint(s2);
  1069.    {  writeln('hexaddresstolongint [',s1,'] [',s2,'] ',l1,'  ',l2);}
  1070.      HexAddressToLongInt := (l1 * 16) + l2;
  1071.      end;
  1072.  
  1073.  
  1074. {section  HexToByte }
  1075. Function  HexToByte( st : string) : byte;
  1076. var  s     : string[3];
  1077.      b1,b2     : byte;
  1078.      begin
  1079.      HexToByte := 0;
  1080.      s := st;
  1081.      if s[1] = '$' then delete(s,1,1);
  1082.      if length(s) < 2 then exit;
  1083.      if ord(s[1]) < ord('A') then b1 := ((ord(s[1])-48)and $F)
  1084.      else b1 := ((ord(s[1])-55) and $F);
  1085.      if ord(s[2]) < ord('A') then b2 := ((ord(s[2])-48)and $F)
  1086.      else b2 := ((ord(s[2])-55) and $F);
  1087.      HexToByte := (b1 * 16) + b2;
  1088.      end;
  1089.  
  1090.  
  1091. {section  HexCharToByte }
  1092. Function  HexCharToByte( chr : char) : byte;
  1093. var b : byte;
  1094.     ch : char;
  1095.      begin
  1096.      ch := UpCase(chr);
  1097.      if ord(ch) < ord('A') then b := ((ord(ch)-48)and $F)
  1098.      else b := ((ord(ch)-55) and $F);
  1099.      HexCharToByte := b;
  1100.      end;
  1101.  
  1102.  
  1103. {section  HexToLongInt }
  1104. Function  HexToLongInt(s : string) : longint;
  1105. var l1,l : longint;
  1106.     ll   : byte;
  1107.     s1   : string[6];
  1108.     nibble : string;
  1109.      begin
  1110.      s1 := s;
  1111.      ll := length(s1);
  1112.      if (ll div 2) * 2 <> ll then s1 := '0' + s1;
  1113.      l  := 0;
  1114.      while length(s1) > 0 do
  1115.           begin
  1116.           nibble := s1;
  1117.           delete(s1,1,2);
  1118.           l1 := hextobyte(nibble);
  1119.           l := l * $100 + l1;
  1120.           end;
  1121.      HexToLongInt := l;
  1122.      end;
  1123.  
  1124.  
  1125. {section  Int2Real }
  1126. Function  Int2Real(i : Integer) : real;
  1127. var y     : real;
  1128.      begin
  1129.      y := i;
  1130.      Int2Real := y / 8.0;
  1131.      end;
  1132.  
  1133.  
  1134. {section IntegerStr }
  1135. Function IntegerStr( I : integer; L : integer ) : string;
  1136. var S : string;
  1137.     begin
  1138.     Str(I,S);
  1139.     IntegerStr := RightStr(S,L);
  1140.     end;
  1141.  
  1142.  
  1143. {section LeftStr }
  1144. Function LeftStr( St : string; L : integer ) : string;
  1145.      begin
  1146.      LeftStr := copy(St+conststr(' ',L-length(St)),1,l);
  1147.      end;
  1148.  
  1149.  
  1150. {section LJStr }
  1151. Function LJStr(s : string; w : byte) : string;
  1152.            {[STRING] Left justifies a string in a field of specified width }
  1153. var NewStr : string;
  1154.      begin
  1155.      FillChar(NewStr, SizeOf(NewStr), ' ');
  1156.      NewStr    := s;
  1157.      NewStr[0] := CHR(w);
  1158.      LJStr     := NewStr
  1159.      end;
  1160.  
  1161.  
  1162. {section  LongIntStr }
  1163. Function  LongIntStr( I : longint; L : integer ) : string;
  1164. var S : string;
  1165.     begin
  1166.     Str(I,S);
  1167.     LongintStr := RightStr(S,L);
  1168.     end;
  1169.  
  1170.  
  1171. {section MakeDir }
  1172. Function MakeDir(dirname : string) : boolean;
  1173.                  {[FILE] does MD <dir> command }
  1174. var fn : string;
  1175.     err : integer;
  1176.      begin
  1177.      fn := DeleteBackSlash(FilePathStr(dirname));
  1178.      {writeln('MakeDir [',fn,']');}
  1179.      {$I-} MkDir(fn); {$I+}
  1180.      err := IOResult;
  1181.      if err <> 0 then writeln('MakeDir failed ',err);
  1182.      MakeDir := fileexistsMSG(fn+'.','','Dir not Found');
  1183.      end;
  1184.  
  1185.  
  1186. {section MAX }
  1187. Function Max(i1,i2 : integer) : integer;
  1188.      begin
  1189.      if i1 < i2 then max := i2
  1190.      else max := i1;
  1191.      end;
  1192.  
  1193.  
  1194. {section MergeStr }
  1195. Function MergeStr( s : string; posn : integer; s1 : string) : string;
  1196. var i,j,n,p : integer;
  1197.     st      : string;
  1198.     begin
  1199.     st := s;
  1200.     p := posn;
  1201.     if p < 1 then p := 1;
  1202.     if (p > 253) then exit;
  1203.     i := length(s1);
  1204.     n := p+i-1;
  1205.     if n > 253 then i := 253 - n;
  1206.     if n > length(st) then st := leftstr(st,n);
  1207.     move(s1[1],st[p],i);
  1208.     Mergestr := st;
  1209.     end;
  1210.  
  1211.  
  1212. {section MIN }
  1213. Function Min(i1,i2 : integer) : integer;
  1214.      begin
  1215.      if i1 < i2 then min := i1
  1216.      else min := i2;
  1217.      end;
  1218.  
  1219.  
  1220. {section  MiscDelayNTicks }
  1221. Procedure MiscDelayNTicks(n : longint);
  1222.       {[DATETIME] A delay of 1 seems to be about 0.05 seconds}
  1223. var j : integer;
  1224.     t : longint;
  1225.      begin
  1226.      if n = 0 then exit;
  1227.      for j := 1 to n do
  1228.           begin
  1229.           t := TicksSinceMidnight;
  1230.           while TicksSinceMidnight = t do begin end;
  1231.           end;
  1232.      end;
  1233.  
  1234.  
  1235. {section  NumericsOnlyStr }
  1236. Function  NumericsOnlyStr(s : string) : string;
  1237. var i  : integer;
  1238.     s1 : string;
  1239.      begin
  1240.      s1 := '';
  1241.      if length(s) > 0 then
  1242.           begin
  1243.           for i := 1 to length(s) do
  1244.               if s[i] in ['0'..'9','-'] then s1 := s1 + s[i];
  1245.           end;
  1246.      NumericsOnlyStr := s1;
  1247.      end;
  1248.  
  1249.  
  1250.  
  1251. {section  PackTimeStr }
  1252. Function  PackTimestr(PT : longint) : string;
  1253. var d : DateTime;  { DOS }
  1254. var temp : string[14];
  1255.     begin
  1256.     UnPackTime(PT,d);
  1257.     temp :=  FmtYMD(d.year,d.month,d.day) + ' ' +
  1258.                     FmtHMS(d.hour,d.min,d.sec);
  1259.     PackTimestr := temp;
  1260.     end;
  1261.  
  1262.  
  1263. {section  Pad }
  1264. Function  Pad(n : integer) : string;
  1265.            {[MISC] - Generates a string of n blanks }
  1266. var i : integer;
  1267.     s : string;
  1268.      begin
  1269.      if n < 1 then s := ''
  1270.      else s := conststr(' ',n);
  1271.      Pad := s;
  1272.      end;
  1273.  
  1274.  
  1275. {section  PatchStr }
  1276. Procedure PatchStr(var s : string; ch1,ch2 : char);
  1277. var i : integer;
  1278.     begin
  1279.     i := 1;
  1280.     while i <= length(s) do
  1281.          begin
  1282.          if s[i] = ch1 then s[i] := ch2;
  1283.          inc(i);
  1284.          end;
  1285.     end;
  1286.  
  1287.  
  1288. {section PctStr }
  1289. Function PctStr(x,y : real; L,D : integer) : string;
  1290. var s : string;
  1291.     z : real;
  1292.      begin
  1293.      z := (x/(y+0.00001)) * 100;
  1294.      if z > 9999 then z := 9999;
  1295.      s := realstr(z,L,D);
  1296.      PctStr := s + '%';
  1297.      end;
  1298.  
  1299.  
  1300. {section ProperName }
  1301. Function ProperName(s : string) : string;
  1302. { Converts a string to lower case characters and capitalizes first letter}
  1303. var i : integer;
  1304.     b : byte;
  1305.      begin
  1306.      s := DnCaseStr(s);
  1307.      s[1] := Upcase(s[1]);
  1308.      ProperName := s;
  1309.      end;
  1310.  
  1311.  
  1312. {section  QT }
  1313. Function  QT(s : string) : string;    { makes a string with quotes around it }
  1314.      begin
  1315.      QT := '''' + s + '''';
  1316.      end;
  1317.  
  1318.  
  1319. {section  RandomInt }
  1320. Function  RandomInt(i1,i2 : integer) : integer;
  1321.              {[MISC] Returns random integer  i1 <= i <= i2  }
  1322. var i,j2 : integer;
  1323.      begin
  1324.      j2 := abs(i2-i1);
  1325.      randomize;
  1326.      i := trunc(random(j2)) + i1;
  1327.      if i < 1 then i := i1
  1328.      else if i > i2 then i := i2;
  1329.      RandomInt := i;
  1330.      end;
  1331.  
  1332.  
  1333. {section Real2Int }
  1334. Function Real2Int(x : real) : Integer;
  1335. { pack reals in range -4095 to +4095 to an integer }
  1336. { resolution is to 1/8                             }
  1337. var y     : real;
  1338.     l     : longint;
  1339.      begin
  1340.      Real2Int := 0;
  1341.      l := abs(trunc(x*8));
  1342.      if (l > 32760) then l := 32760;
  1343.      if x < 0 then l := -1 * l;
  1344.      Real2Int := l;
  1345.      end;
  1346.  
  1347.  
  1348. {section RealStr }
  1349. Function RealStr( R : real; L,D : integer ) : string;
  1350. var S : string;
  1351.     begin
  1352.     Str(R:12:D,S);
  1353.     RealStr := RightStr(S,L);
  1354.     end;
  1355.  
  1356.  
  1357. {section RealZero }
  1358. Function RealZero( x : real) : boolean;
  1359.      begin
  1360.      if abs(x) < 0.01 then RealZero := true
  1361.      else RealZero := false;
  1362.      end;
  1363.  
  1364.  
  1365. {section  RemoveBlanks }
  1366. Procedure RemoveBlanks(var astring : string);
  1367. var j : integer;
  1368.     begin
  1369.     j := 1;
  1370.     while j <= length(astring) do
  1371.         begin
  1372.         if (astring[j] = ' ') then delete(astring,j,1)
  1373.         else inc(j);
  1374.         end;
  1375.     end;
  1376.  
  1377.  
  1378. {section RemoveBrackets }
  1379. Function RemoveBrackets(s : string) : string;
  1380. var len : integer;
  1381.     s1  : string;
  1382.     begin
  1383.     len := length(s);
  1384.     s1  := trimstr(s);
  1385.     if len > 2 then
  1386.          begin
  1387.          case s1[1] of
  1388.              '[' :  begin
  1389.                     if s1[len] = ']'   then RemoveEnds(s1);
  1390.                     end;
  1391.              '{' :  begin
  1392.                     if s1[len] = '}'   then RemoveEnds(s1);
  1393.                     end;
  1394.              '(' :  begin
  1395.                     if s1[len] = ')'   then RemoveEnds(s1);
  1396.                     end;
  1397.              '''' : begin
  1398.                     if s1[len] = ''''  then RemoveEnds(s1);
  1399.                     end;
  1400.              '"'  : begin
  1401.                     if s1[len] = '"'   then RemoveEnds(s1);
  1402.                     end;
  1403.              '<'  : begin
  1404.                     if s1[len] = '>'   then RemoveEnds(s1);
  1405.                     end;
  1406.              else   begin end;
  1407.              end;
  1408.          end;
  1409.      RemoveBrackets := s1;
  1410.      end;
  1411.  
  1412.  
  1413. {section  RemoveEnds }
  1414. Procedure RemoveEnds(var s : string);
  1415.      begin
  1416.      if length(s) < 2 then exit;
  1417.      delete(s,1,1);
  1418.      delete(s,length(s),1);
  1419.      end;
  1420.  
  1421.  
  1422. {section  RemoveExcessBlanks }
  1423. Procedure RemoveExcessBlanks(var astring : string);
  1424. var prev : char;
  1425.     j    : integer;
  1426.     begin
  1427.     prev := ' ';
  1428.     j := length(astring);
  1429.     if j > 0 then
  1430.         begin
  1431.         j := 1;
  1432.         repeat
  1433.             begin
  1434.             if (astring[j] = ' ') and (prev = ' ') then delete(astring,j,1)
  1435.             else
  1436.                 begin
  1437.                 prev := astring[j];
  1438.                 j := j + 1;
  1439.                 end;
  1440.             end;
  1441.         until j > length(astring);
  1442.         end;
  1443.     end;
  1444.  
  1445.  
  1446. {section  RemoveLeading }
  1447. Procedure RemoveLeading(var s : string; ch : CHAR);
  1448. var P : Byte;
  1449.      begin
  1450.      P := 1;
  1451.      while (S[P] = ch) and (P <= length(S)) DO Inc(P);
  1452.      if P > 1 then
  1453.           begin  { equiv to delete(s,1,P) }
  1454.           Move(S[P], S[1], succ(length(S) - P));
  1455.           Dec(S[0], pred(P));
  1456.           end;
  1457.      end;
  1458.  
  1459.  
  1460. {section  RemoveTrailing }
  1461. Procedure RemoveTrailing(var s : string; ch : CHAR);
  1462. { Remove specified trailing characters from string }
  1463.        begin
  1464.        while S[length(S)] = ch DO Dec(S[0]);
  1465.        end;
  1466.  
  1467.  
  1468. {section RenameFile }
  1469. Function RenameFile(fname1,fname2 : string) : boolean;
  1470.                   {[FILE] Returns false if fails. }
  1471. var fil : file;
  1472.     err : integer;
  1473.      begin
  1474.      RenameFile := false;
  1475.      assign(fil,fname1);
  1476.      {$I-} rename(fil,fname2); {$I+}
  1477.      err := IOResult;
  1478.      if err = 0 then RenameFile := true
  1479.      else writeln('RenameFile error ',err);
  1480.      {$I-} close(fil); {$I+}
  1481.      err := IOResult;  {ignore error on close}
  1482.      end;
  1483.  
  1484.  
  1485. {section  ReplaceStr }
  1486. Procedure ReplaceStr( var Str : string; Offset : integer; S1 : string);
  1487.      begin
  1488.      Str := Str + conststr(' ',offset-length(Str));
  1489.      Delete(Str,Offset,length(S1));
  1490.      Insert(S1,Str,Offset);
  1491.      end;
  1492.  
  1493.  
  1494. {section RightStr }
  1495. Function RightStr( St : string; l : integer ) : string;
  1496. var S : string;
  1497.      begin
  1498.      s := conststr(' ',L-length(St))+St;
  1499.      RightStr := copy(s,(length(s)-l)+1,l);
  1500.      end;
  1501.  
  1502.  
  1503. {section RJStr }
  1504. Function RJStr(s : string; w : byte) : string;
  1505.           {[STRING] Right justifies a string in a field of specified width }
  1506. var NewStr : string;
  1507.      begin
  1508.      NewStr := s;
  1509.      while length(NewStr) < w do
  1510.           insert(' ', NewStr, 1);
  1511.      RJStr := NewStr
  1512.      end;
  1513.  
  1514.  
  1515.  
  1516. {section  RotateStringL }
  1517. Procedure RotateStringL(var st : string);
  1518. var ch :char;
  1519.      begin
  1520.      ch := st[1];
  1521.      delete(st,1,1);
  1522.      st := st + ch;
  1523.      end;
  1524.  
  1525.  
  1526.  
  1527. {section  SameFile }
  1528. Function  SameFile(fn1,fn2 : string) : boolean;
  1529. var same : boolean;
  1530.     sr1, sr2 : searchrec;
  1531.      begin
  1532.      same := false;
  1533.      if (fileInfo(fn1,'',sr1) = 0) and
  1534.         (fileInfo(fn2,'',sr2) = 0) then
  1535.           begin
  1536.           if (sr1.size = sr2.size) and
  1537.              (sr1.time = sr2.time) and
  1538.              (sr1.name = sr2.name) then same := true;
  1539.           end;
  1540.      SameFile := same;
  1541.      end;
  1542.  
  1543.  
  1544. {section  SetDateBytes }
  1545. Procedure SetDateBytes(var yr,mo,dy : byte);
  1546. var year,month,day,doy : word;
  1547.      begin
  1548.      getdate(year,month,day,doy);
  1549.      yr := year-1900;
  1550.      mo := month;
  1551.      day := dy;
  1552.      end;
  1553.  
  1554.  
  1555. {section SizeofFile }
  1556. Function SizeofFile(fname : string; ext : string) : longint;
  1557. var l : longint;
  1558.     fn : string;
  1559.     SR : searchrec;
  1560.      begin
  1561.      fn := fname;
  1562.      l := 0;
  1563.      if ext <> '' then ForceExt(fn,ext);
  1564.      FindFirst(fn,anyfile,SR);
  1565.      if dosError = 0 then l := SR.size;
  1566.      SizeofFile := l;
  1567.      end;
  1568.  
  1569.  
  1570. {section  StrBool }
  1571. Function  StrBool (s : string) : boolean;
  1572. var x : boolean;
  1573.     s1 : string;
  1574.     code : integer;
  1575.      begin
  1576.      x := true;
  1577.      s1 := UpCaseStr(s);
  1578.      if (s1 = 'NO') or (s1 = 'OFF') then x := false;
  1579.      StrBool := x;
  1580.      end;
  1581.  
  1582.  
  1583. {section  StrCal }
  1584. Procedure StrCal(ds : string; var dd,mm,yy : integer);
  1585. var s,ss : string[8];
  1586.     i,l : word;
  1587.     err,defyear,defmonth,defday : word;
  1588.     begin
  1589.     s := ds;
  1590.     getdate(defyear,defmonth,defday,err);
  1591.     defyear := defyear mod 100;
  1592.     l := length(s);
  1593.     if l = 0 then
  1594.          begin
  1595.          dd := defday;
  1596.          mm := defmonth;
  1597.          yy := defyear;
  1598.          exit;
  1599.          end;
  1600.     for i := 1 to l do if s[i] = '-' then s[i] := '/';
  1601.     for i := 1 to l do
  1602.          if not (s[i] in ['0'..'9','/']) then s[i] := ' ';
  1603.     removeblanks(s);
  1604.     while length(s) <> 8 do
  1605.         begin
  1606.         if s[2] = '/' then
  1607.              begin
  1608.              s := '0' + s;
  1609.              l := length(s);
  1610.              end;
  1611.         case l of
  1612.             1..2   :  begin         { d,dd }
  1613.                       s := integerstr(defmonth,2) + '/' + s;
  1614.                       s := s + '/' + integerstr(defyear,2);
  1615.                       removeblanks(s);
  1616.                       end;
  1617.  
  1618.             3..5   :  begin  {m/d,mm/d,mm/dd - add year}
  1619.                       s := s + '/' + integerstr(defyear,2);
  1620.                       removeblanks(s);
  1621.                       end;
  1622.  
  1623.             7      :  begin   {mm/d/yy, mm/dd/y}
  1624.                       if      s[5] = '/' then insert('0',s,4)
  1625.                       else if s[6] = '/' then insert('0',s,6)
  1626.                       else s := '01/01/01';
  1627.                       end;
  1628.             8       : begin end;
  1629.  
  1630.             else s := '01/01/01';
  1631.             end;
  1632.         l := length(s);
  1633.         end;
  1634.     ss := copy(s,1,2);
  1635.     val(ss,mm,err);
  1636.     ss := copy(s,4,2);
  1637.     val(ss,dd,err);
  1638.     ss := copy(s,7,2);
  1639.     val(ss,yy,err);
  1640.     end;
  1641.  
  1642.  
  1643. {section  StrByte }
  1644. Function  StrByte(s : string) : byte;
  1645. var  x,err  : integer;
  1646.      begin
  1647.      x := 0;
  1648.      val(s,x,err);
  1649.      if err > 1 then val(copy(s,1,err-1),x,err);
  1650.      StrByte := byte(x);
  1651.      end;
  1652.  
  1653.  
  1654. {section  StrInt }
  1655. Function  StrInt(s : string) : integer;
  1656. var  x,err  : integer;
  1657.      begin
  1658.      x := 0;
  1659.      val(s,x,err);
  1660.      if err > 1 then val(copy(s,1,err-1),x,err);
  1661.      StrInt := x;
  1662.      end;
  1663.  
  1664.  
  1665. {section  StrLong }
  1666. Function  StrLong(s : string) : longint;
  1667. var  err  : integer;
  1668.      x    : longint;
  1669.      begin
  1670.      x := 0;
  1671.      val(s,x,err);
  1672.      if err > 1 then val(copy(s,1,err-1),x,err);
  1673.      StrLong := x;
  1674.      end;
  1675.  
  1676.  
  1677. {section  StrReal }
  1678. Function  StrReal(s : string) : real;
  1679. var  err  : integer;
  1680.      x    : real;
  1681.      begin
  1682.      x := 0;
  1683.      val(s,x,err);
  1684.      if err > 1 then val(copy(s,1,err-1),x,err);
  1685.      StrReal := x;
  1686.      end;
  1687.  
  1688.  
  1689. {section  SuggestExt }
  1690. Procedure SuggestExt(var fname : string; ext : string);
  1691.                         {[FILE] only if EXT not specified}
  1692. var i : integer;
  1693.     begin
  1694.     i := pos('.',fname);
  1695.     if (i = 0) or (i = length(fname)) then ForceExt(fname,ext);
  1696.     end;
  1697.  
  1698.  
  1699. {section TicksSinceMidnight }
  1700. Function TicksSinceMidnight : longint;
  1701. var hr,mn,sc,sc100 : word;
  1702.      begin
  1703.      GetTime(hr,mn,sc,sc100);
  1704.      TicksSinceMidnight := sc100 + (sc * onehundred) +
  1705.                                    (mn * 60 * onehundred) +
  1706.                                    (hr * 36 * tenthousand);
  1707.      end;
  1708.  
  1709.  
  1710. {section TicksToSecs }
  1711. Function TicksToSecs ( t : longint ) : real;
  1712.      begin
  1713.      TicksToSecs := t / 100.0;
  1714.      end;
  1715.  
  1716.  
  1717. {section TicksToSecsStr }
  1718. Function TicksToSecsStr ( t : longint ) : string;
  1719. var hr,mn,sc,tk : word;
  1720.     tx          : longint;
  1721.      begin
  1722.      mn := 0;     sc := 0;     tk := 0;
  1723.      tx := t;
  1724.      hr := word(tx div 360000);
  1725.      tx := tx -  (hr * 360000);
  1726.      if tx > 0 then
  1727.           begin
  1728.           mn := word(tx div 6000);
  1729.           tx := tx -  (mn * 6000);
  1730.           if tx > 0 then
  1731.                begin
  1732.                sc := word(tx div 100);
  1733.                tx := tx -  (sc * 100);
  1734.                end;
  1735.           tk := word(tx);
  1736.           end;
  1737.      TicksToSecsStr :=  FmtHMS(hr,mn,sc)+'.'+integerstr(tk+100,2);
  1738.      end;
  1739.  
  1740.  
  1741. {section TimerSecs }
  1742.  
  1743. var TimerHold : longint;
  1744.  
  1745. Procedure TimerSecsReset;
  1746.        {[TIME] Manual Reset for TimerSecs. }
  1747.      begin
  1748.      TimerHold := 0;
  1749.      end;
  1750.  
  1751.  
  1752. Function TimerSecs : Integer;
  1753.        {[TIME] A small rough timer, Resets itself each 1000 seconds. }
  1754. var x,y : longint;
  1755.      begin
  1756.      x := TicksSinceMidnight;
  1757.      if (x < TimerHold) then TimerHold := TicksSinceMidNight;
  1758.      y := x - TimerHold;
  1759.      if (y > 100000) then
  1760.           begin
  1761.           TimerHold := TicksSinceMidNight;
  1762.           y := x - TimerHold;
  1763.           end;
  1764.      TimerSecs := integer(y div 100);
  1765.      end;
  1766.  
  1767.  
  1768.  
  1769.  
  1770. {section  Trim }
  1771. Procedure Trim(var s : string);
  1772. var i : integer;
  1773.      begin
  1774.      RemoveTrailing(s,' ');
  1775.      RemoveLeading(s,' ');
  1776.      end;
  1777.  
  1778.  
  1779. {section TrimStr }
  1780. Function TrimStr(s : string) : string;
  1781. var s1 : string;
  1782.      begin
  1783.      s1 := s;
  1784.      trim(s1);
  1785.      TrimStr := s1;
  1786.      end;
  1787.  
  1788.  
  1789. {section UnCompressStr }
  1790. Function UnCompressStr(s : string) : string;
  1791. var ls,j,k,rc : integer;
  1792.     s2      : string;
  1793.     ch      : char;
  1794.     begin
  1795.     ls := length(s);
  1796.     s2 := '';
  1797.     j := 1;
  1798.     while j <= ls  do
  1799.         begin
  1800.         if (ord(s[j]) < (160+1)) then s2 := s2 + s[j]
  1801.         else
  1802.             begin
  1803.             ch := s[j-1];
  1804.             rc := ord(s[j]) - 160;
  1805.             for k := 1 to rc do s2 := s2 + ch;
  1806.             end;
  1807.         inc(j);
  1808.         end;
  1809.     UnCompressStr := s2;
  1810.     end;
  1811.  
  1812.  
  1813. {section  UnQT }
  1814. Function  UnQT(s : string) : string;    { removes quotes from around a string }
  1815. var s1 : string;
  1816.      begin
  1817.      s1 := s;
  1818.      if s1[1] = '''' then delete(s1,1,1);
  1819.      if s1[length(s1)] = '''' then delete(s1,length(s1),1);
  1820.      UnQT := s1;
  1821.      end;
  1822.  
  1823.  
  1824.  
  1825. {section UpCaseStr }
  1826. Function UpCaseStr(s : STRING) : string;
  1827. { Converts a string to upper case characters }
  1828. var i : integer;
  1829.      begin
  1830.      for i := 1 to length(s) do
  1831.          s[i] := UpCase(s[i]);
  1832.      UpCaseStr := s
  1833.      end;
  1834.  
  1835.  
  1836. {section VolumeLabel }
  1837. Function VolumeLabel( drive : string) : string;
  1838. var SR : searchrec;
  1839.      begin
  1840.      FindFirst(drive+'*.*',VolumeID,SR);
  1841.      if (DOSError = 0) then
  1842.           VolumeLabel := SR.Name
  1843.      else VolumeLabel := '';
  1844.      end;
  1845.